Nuxt3 npm run build后,上传文件后与如何显示问题,可以留意几个点

~/pages/upload.vue

  • 注意 ‘onChangeFile’ 和 ‘FormData’

    <template>
      <div>
          <h1 class="text-3xl mb-3">Profile</h1>
          <UForm ref="form" :state="state" @submit.prevent="save()">
              <UAlert v-if="sucMessage" size="md" icon="i-heroicons-check-circle" title="" color="green" variant="subtle" class="mb-1" :description="sucMessage" />
              <div v-else-if="errorMessage">
                  <UAlert size="md" icon="i-heroicons-exclamation-triangle" title="" v-for="(msg, key) in errorMessage" :key="key" color="red" variant="subtle" class="mb-1" :description="$t(msg)" />
              </div>
              <UFormGroup :label="Photo" name="photo" class="mb-2">
                  <UInput type="file" v-model="state.photo" multiple @change="onChangeFile" />
              </UFormGroup>
              <div class="mb-3">
                  <UButton :disabled="isSubmitting" size="md" type="submit" color="primary" variant="solid" class="mr-1">Submit</UButton>
              </div>
          </UForm>
      </div>
    </template>
    <script setup>
    const { t } = useI18n();
    const isSubmitting = ref(false);
    const form = ref();
    const errorMessage = ref([]);
    const sucMessage = ref('');
    const state = ref({
      photo: undefined,
    });
    state.value.photo = '';
    const formData = new FormData();
    const onChangeFile = (event) => {
      for (let i = 0; i < event.target.files.length; i++) {
          formData.append('photo', event.target.files[i], event.target.files[i].name);
      }
    }
    async function save(){
      isSubmitting.value = true;
      try {
          sucMessage.value = '';
          errorMessage.value = {};
          let response = '';
          try {
              const res = await useFetch((`/api/upload`, {
                  method: 'POST',
                  body: formData
              });
              response = res.data;
          } catch (error) {
              console.error('An error occurred while making the request:', error);
          }
          if (response && response.value.code === 200) {
              state.value.photo = '';
              formData.delete('photo');
              isSubmitting.value= false;
              sucMessage.value = t("update.success");
          }
          else {
              form.value.setErrors(response.value.errors.map((err) => {
                  if(err.field){
                      return { path: err.field, message: t(err.message) };
                  }
              }));
              isSubmitting.value= false;
          }
      } catch (error) {
          errorMessage.value.errors = t("update.error");
          isSubmitting.value = false;
      }
    }
    </script>

    ~/server/api/upload.post.js

  • 这是上传图片api, 注意‘uploadDir’:uploads 路径保持一致

    import path from "path";
    import fs from "fs";
    import { fileURLToPath } from 'url';
    import { writeFile } from "fs/promises";
    export default defineEventHandler(async (event) => {
      try {
          const errors = [];
          const files = await readMultipartFormData(event);
          if (files.length === 0) {
              errors.push({field: 'photo', message: "account.avatar.error.required"});
              return {
                  code: 400,
                  msg: "failed",
                  errors,
              }
          }
          const __filename = fileURLToPath(import.meta.url);
          const __dirname = path.dirname(__filename);
          let uploadDir = path.join(__dirname, "../public/uploads");
          if (process.env.NODE_ENV === 'development') {
              uploadDir = path.join(__dirname, "../../public/uploads");
          }
          if (!fs.existsSync(uploadDir)){
              fs.mkdirSync(uploadDir);
          }
          for(const file of files) {
              const filename = path.basename(file.filename);
              const newFilename = String(Date.now()) + String(Math.round(Math.random() * 100000));
              const newPath = `${path.join(uploadDir, newFilename)}-${filename}`;
              // console.log("newPath:", newPath);
              await writeFile(newPath, file.data);
          }
          return {
              code: 200,
              msg: "success",
          }
      } catch (error) {
          console.log("error:", error);
      }
    });

    ~/server/routes/files/[name].get.js

  • 解读图片或文件,注意 ‘uploadDir’: uploads 路径需和上传api 保持一致

  • 解读地址是:localhost:3000/files/filename.png 就可以看到的

    import fs from "fs";
    import path from "path";
    import { fileURLToPath } from 'url';
    export default defineEventHandler(async (event) => {
      const __filename = fileURLToPath(import.meta.url);
      const __dirname = path.dirname(__filename);
    
      let uploadDir = path.join(__dirname, "../public/uploads");
      if (process.env.NODE_ENV === 'development') {
          uploadDir = path.join(__dirname, "../../public/uploads");
      }
      if (!fs.existsSync(uploadDir)){
          fs.mkdirSync(uploadDir);
      }
      // console.log("uploadDir:", uploadDir);
      const filePath = path.join(uploadDir, event.context.params.name);
      return sendStream(event, fs.createReadStream(filePath));
    });
本作品采用《CC 协议》,转载必须注明作者和本文链接
全栈程序员(Blockchain, Web3, Nuxt3+, vue3+, React18+, PHP, MySQL, HTML, CSS, JavaScrIpt/JQuery)
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!