上傳文件
-
客戶端
打開本地文件// ts 代碼 // 選擇本地文件,以下callback爲函數回調參數 public static openLocalFile(callback: (file: File) => void) { let inputEl: HTMLInputElement = <HTMLInputElement>document.getElementById('file_input');// 類型轉行 HTMLInputElement ,方便下面的 inputEl.files 調用 if (!inputEl) { // 只創建一次 console.log('xxxxxx createElement input'); inputEl = document.createElement('input'); inputEl.id = 'file_input'; inputEl.setAttribute('id', 'file_input'); inputEl.setAttribute('type', 'file'); inputEl.setAttribute('class', 'fileToUpload'); inputEl.style.opacity = '0';// 不可見 inputEl.style.position = 'absolute'; document.body.appendChild(inputEl); } // 這個和 inputEl.onchange 的效果是一樣的,2選1就可以了 // inputEl.addEventListener('change', (event) => { // console.log('xxx onchange1', event, inputEl.value); // }); inputEl.onchange = (event) => { // console.log('xxx onchange2', event, inputEl.files); let files = inputEl.files;// 我在Mac上測試,每次只能選一個文件 if (files && files.length > 0) { var file = files[0]; if (callback) callback(file); } } inputEl.click();// 模擬點擊,觸發文件選擇彈出框,據說有的瀏覽器不支持,chrome是沒問題的 }
發送上傳文件消息
// ts 代碼 public upload(file: File) { // 使用表單設置文件,發送上傳消息到服務器 let forms = new FormData(); forms.append("file", file);// 必填,key不限制必須"file",根據nestjs服務器邏輯填寫 forms.append('fileName', file.name);// 選填,根據nestjs服務器邏輯填寫 forms.append('targetPath', 'test');// 選填,根據nestjs服務器邏輯填寫 let xhr = cc.loader.getXMLHttpRequest();//new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status <= 300 || xhr.status == 304) { console.log(xhr.response) } } else { console.log(xhr.status) } } xhr.open('POST', 'http://localhost:443/api/v1/upload', true); // xhr.setRequestHeader 的問題卡了好久, // nestjs那邊一直報錯,nestjs的文檔要求是 multipart/form-data 格式, // 但是要是你自己設置的話會導致 Boundary 丟失,nestjs 的multer中間件解析錯誤,報錯"Multipart: Boundary not found", // 所以不設置"multipart/form-data",自動生成就好,可以在network裏查看發送的消息頭已經自動添加好了"Content-Type", // 網上各路大神各種花式解決方案,都未解決我的困惑,最後參考這個鏈接解決,跪謝https://blog.csdn.net/yun_hou/article/details/97004557 // xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");// multer不會處理非"multipart/form-data"表單 // xhr.setRequestHeader("Content-Type", "multipart/form-data"); // console.log(forms);// 打印不出來什麼的,所以放棄吧 xhr.addEventListener("progress", function (evt) { console.log('xxx progress', evt);// 上傳進度,我只看到打印一次 }, false); xhr.send(forms); }
本地圖片通過sprite展示
// ts 代碼 // 展示本地圖片到sprite public showImage(file: File, sprite: cc.Sprite) { if (!file) return; // 讀取文件爲base64數據流 readFile(file, (base64: string) => { base64ToSpriteFrame(base64, (spriteFrame: cc.SpriteFrame) => { if (sprite) sprite.spriteFrame = spriteFrame; }); }); } // 讀取文件爲base64數據流 public readFile(file: File, callback: (base64: string) => void) { var reader = new FileReader(); reader.onload = function (event2) { if (callback) { if (reader.readyState == FileReader.DONE) { // console.log('xxx FileReader', event2, reader.result); callback(reader.result.toString()); } else { console.error('FileReader read error', event2, reader.result); callback(null); } } }; // reader.readAsText(file);//作爲字符串讀出 reader.readAsDataURL(file); //reader.readAsText(file,'gb2312');//默認是用utf-8格式輸出的,想指定輸出格式就再添加一個參數,像txt的ANSI格式只能用國標才能顯示出來 } // public base64ToSpriteFrame(base64: string, callback: (this: void, spriteFrame: cc.SpriteFrame) => void) { var img = new Image(); console.warn("------------準備合成-------------") img.onload = function () { console.warn("*********img.onload**********") var texture = new cc.Texture2D(); texture.initWithElement(img); texture.handleLoadedTexture(); var newframe = new cc.SpriteFrame(texture); if (callback) callback(newframe); } img.onerror = function (err) { console.warn("------合成報錯-----", err) } if ((<any>base64).startsWith !== undefined && (<any>base64).startsWith("data:image")) { img.src = base64; } else { img.src = "data:image/png;base64," + base64; } }
-
服務器
// nestjs // main.ts import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as cors from 'cors'; // import { NestExpressApplication } from '@nestjs/platform-express'; async function bootstrap() { const app = await NestFactory.create(AppModule); // const app = await NestFactory.create< NestExpressApplication>(AppModule);// 有說新版本要這麼寫,我的nestjs版本是7.1.2,沒這麼寫也能用 // 跨域 app.use(cors({ origin: '*', credentials: true })); await app.listen(3000); } bootstrap();
// nestjs 單文件上傳處理事例,這個搞通了多文件參考網上其他教程就也差不多能搞出來了 // app.controller.ts import { Controller, Get, Post, Body, UseInterceptors, UploadedFile } from '@nestjs/common'; import { AppService } from './app.service'; import { FileFieldsInterceptor, FileInterceptor } from '@nestjs/platform-express'; import { createWriteStream } from 'fs'; import { join } from 'path'; // 網上好多教程都不給import部分,對於一個小白來說我知道 createWriteStream 和 join 是個鬼哦 @Controller("api/v1") export class AppController { constructor(private readonly appService: AppService) {} @Post("upload") @UseInterceptors(FileInterceptor('file')) async uploadFile(@UploadedFile() file, @Body() body) { console.log('upload file', file); // console.log('upload body', body); // 這個文件路徑是參照本文件的,路徑不對的話多試幾次吧,或者自己加個路徑檢測的代碼,缺少對應路徑記得自己創建哈 const writeImage = createWriteStream(join(__dirname, '../../../public/upload/', `${file.originalname}`)); writeImage.write(file.buffer); return '上傳圖片成功'; } }
下載文件
-
客戶端
// ts 代碼 // cocos creator 客戶端下載 downloadImage(fileName: string, sprite: cc.Sprite) { let progressCallback = (completedCount: number, totalCount: number, item: any): void=> { console.log('download progressCallback', completedCount, totalCount, item); } let completeCallback = (error: Error, resource: any): void => { console.log('download completeCallback', error, resource); if (resource && sprite) sprite.spriteFrame = new cc.SpriteFrame(resource); } cc.loader.load('http://localhost:443/api/v1/download/' + fileName, progressCallback, completeCallback); // cc.loader.loadRes只能加載resources路徑下的文件 // cc.loader.getXMLHttpRequest() 需要自己做類型轉換,有需要再嘗試吧 // let xhr = cc.loader.getXMLHttpRequest();//new XMLHttpRequest(); // xhr.onreadystatechange = function () { // if (xhr.readyState == 4) { // // if (xhr.status >= 200 && xhr.status <= 300 || xhr.status == 304) { // // console.log(xhr.response); // // } // if (xhr.status == 200) { // console.log(xhr.response); // } // } else { // // console.log(xhr.status); // } // } // xhr.responseType = 'arraybuffer'; // xhr.open('GET', 'http://localhost:443/api/v1/download/' + fileName, true); // xhr.send(); }
-
服務器
// ts 代碼 // nestjs 服務器下載靜態資源代碼,可以接着前面的上傳代碼寫 import { Controller, Get, Param, Res } from '@nestjs/common'; import { AppService } from './app.service'; import { join } from 'path'; import { Response } from 'express';// 一開始我一直以爲 Response 是 '@nestjs/common' 裏的,呵呵,sendFile一直報錯,後來.....參考https://stackoverflow.com/questions/55325062/how-to-serve-static-html-files-in-nest-js @Controller("api/v1") export class AppController { constructor(private readonly appService: AppService) {} @Get("download/:file") getFile(@Res() res: Response, @Param() params): string { console.log('xxx', params); res.sendFile(join(__dirname, '../../../public/upload', params.file)); return "下載成功"; } }
參考
- https://docs.nestjs.com/techniques/configuration#custom-env-file-path
- https://cloud.tencent.com/developer/section/1490184
- https://www.cnblogs.com/lengyue0030/p/6885107.html
- https://www.jianshu.com/p/eec0586409da
- https://www.cnblogs.com/ajanuw/p/9575278.html
- https://www.cnblogs.com/web-wjg/p/9244074.html
- https://blog.csdn.net/weixin_44273392/article/details/100153051
- https://www.jianshu.com/p/1484605c523a
- https://www.jianshu.com/p/43839abfdc1a
- https://stackoverflow.com/questions/55325062/how-to-serve-static-html-files-in-nest-js
- https://blog.csdn.net/weixin_43660626/article/details/102702461
- https://blog.csdn.net/weixin_34258782/article/details/94613224
- https://www.cnblogs.com/ajanuw/p/9574535.html
- https://blog.csdn.net/qq_27124771/article/details/81208493
- https://www.cnblogs.com/wolf-sun/p/6693367.html
- https://blog.csdn.net/weixin_41646716/article/details/90058189
- https://www.jianshu.com/p/5147e36cf19c
- https://blog.csdn.net/andywei147/article/details/80636539
- https://blog.csdn.net/lck8989/article/details/81021416
- https://www.jianshu.com/p/8fa0fb53c183