1

i am trying to upload large file(0 to 100mb) to azure file share using this @azure/storage-file-share node Js client library.

small files less than 4 MB works good, but more that that is thowing an error (contentLength must be > 0 and <= 4194304 bytes)

My payload is in readable stream and and i am using method uploadRange in the library

here is the below code

{
        method: "POST",
        path: `${apiBase}/mount`,
        config: {
          description: "uploadFile",
          tags: ["api", "file"],
          notes: ["upload a file"],
          auth: {
            strategy: "jwt",
            mode: options.session.auth,
            access: {
              scope: options.session.scope,
            },
          },
          payload: {
            maxBytes: 1024 * 1024 * 200,
            multipart: true,
            parse: true,
            output: "stream",
            allow: "multipart/form-data",
          },
          timeout: {
            server: 10 * 60 * 1000,
            socket: 12 * 60 * 1000,
          },

          response: {
            status: {
              200: Joi.object({
                status: Joi.string(),
                fileUrl: Joi.string(),
                date: Joi.number(),
              }),
              422: Joi.object({
                statusCode: Joi.number().integer(),
                error: Joi.string(),
                message: Joi.string(),
              }),
              503: Joi.object({
                statusCode: Joi.number().integer(),
                error: Joi.string(),
                message: Joi.string(),
              }),
            },
          },
          handler: async (request, h) => {
            if (!request.auth.credentials) {
              throw Boom.unauthorized("unexpected unauthorized error");
            }
            try {
              const azureDirectory = azure.sanitizeContainerName(
                request.auth.credentials.userId
              );
              const azureFileStream = request.payload.file;
              const r = await azure.uploadFileToVolume({
                azureFileServiceClient: options.azureFileServiceClient,
                azureFileVolumeMount: options.azureFileVolumeMount,
                azureFileStream,
                azureDirectory,
              });
              if (r.errorCode) {
                throw Boom.badData(
                  `file upload error due to azure error ${r.errorCode}` +
                    `\n${JSON.stringify(r)}`
                );
              }

              return h.response({
                status: "ok",
                fileUrl:
                  options.azureFileServiceClient.url +
                  azureDirectory +
                  // encode file name
                  `/${encodeURIComponent(azureFileStream.hapi.filename)}`,
                date: new Date(r.lastModified).getTime(),
              });
            } catch (e) {
              throw Boom.serverUnavailable(`file upload error ${e}`);
            }
          },
        },
      }
      
      
exports.uploadFileToVolume = async ({
  azureFileServiceClient,
  azureFileVolumeMount,
  azureFileStream,
  azureDirectory,
}) => {
  const directoryClient = await azureFileServiceClient
    .getShareClient(azureFileVolumeMount)
    .getDirectoryClient(azureDirectory);

  if (!(await directoryClient.exists())) {
    // create azure directory by userid if not exists
    await azureFileServiceClient
      .getShareClient(azureFileVolumeMount)
      .createDirectory(azureDirectory);
  }

  const content = azureFileStream._data;
  const fileName = encodeURIComponent(azureFileStream.hapi.filename);
  const fileClient = directoryClient.getFileClient(fileName);
  await fileClient.create(content.length);

  return await fileClient.uploadRange(content, 0, content.length);

};

can any one help me to get the right method in the library to send the files, i tried to use uploadStream abut it didnt work.

1 Answers1

2

The reason you're getting this error is because the maximum content size allowed for an uploadRange is 4MB. uploadRange operation maps to Put Range REST API operation and the limitation is from the REST API side (see description for Range or x-ms-range in request headers section).

What you have to do is read chunks of your content and then call uploadRange method repeatedly using those chunks. When reading chunks, you have to ensure that the maximum size of the chunk you read does not exceed 4MB.

Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241